﻿using ArtMath.Attribute;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Flag;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.Collections.Generic;

namespace ArtMath.Component.Line
{
    /// <summary>
    /// 两点直线
    /// </summary>
    [Serializable]
    public class TwoPointsStraightLine : PointSlopeLineBase
    {
        public TwoPointsStraightLine(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.ldzx, addToList)
        {
            InPoints = new PointBase[2];
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}1", "Point")]
        public PointBase Point1
        {
            get { return InPoints[0]; }
            set { SetPoint(0, value); }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}2", "Point")]
        public PointBase Point2
        {
            get { return InPoints[1]; }
            set { SetPoint(1, value); }
        }
        public override double NewSlope
        {
            get
            {
                return Point1.NewXY.GetSlope(Point2.NewXY);
            }
        }
        public override double NewPSlope
        {
            get
            {
                return Point1.NewPxy.GetSlope(Point2.NewPxy);
            }
        }
        public override void ComponentChanged(ShapeBase component)
        {
            if (component == Point1 || component == Point2)
            {
                PSlope = NewPSlope;
            }
            base.ComponentChanged(component);
        }
        public override void ComponentBuilding(Base component)
        {
            if (Point1 == null) return;
            if (Flags.Shift && AllowFix)
            {
                SpareCoordinate = SpareCoordinate.GetProjectivePoint(Point1.Pxy, Math.Tan(Utility.GetFixedAngle(
                        Point1.Pxy.GetAngle(SpareCoordinate))));
            }
            PointD xy = Pad.PxyToXY(SpareCoordinate);
            Slope = Point1.ToPointD().GetSlope(xy);
            PSlope = Point1.Pxy.GetSlope(SpareCoordinate);
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}{Resources.LeftParenthesis}{string.Format(Resources.Translate("Of"), Resources.Translate("Point") + "2", Resources.Translate("Coordinate"))}{Resources.ColonSeparate}{Pad.PxyToMath(SpareCoordinate)}");
            base.ComponentBuilding(component);
        }
        public void CreateComponents(PointBase point, bool p2DoBuilding = false)
        {
            if (point == null) return;
            if (Point1 == null)
            {
                Point1 = point;
                SpareCoordinate_ = Point1.Pxy;
                Pad.TrackObj = this;
            }
            else
            {
                if (p2DoBuilding)
                {
                    Pad.HostTrackComponentBuilding(point.Pxy);
                }
                Point2 = point;
                base.CreateComponents();
            }
        }
        public void CreateComponents(string pointName, PointCollectionBase[] collections = null)
        {
            if (collections == null)
            {
                if (Point1 == null)
                {
                    collections = Universal.GenerateInstanceArray();
                }
                else
                {
                    collections = new PointCollectionBase[1];
                    if (Flags.Shift && AllowFix)
                    {
                        collections[0] = new Ray(Point1.ToPointD(), Point1.ToPointD().GetAngle(Pad.PxyToXY(SpareCoordinate)) );
                    }
                    else
                    {
                        collections[0] = new Universal();
                    }
                    collections[0].Exceptions = new HashSet<PointCollectionBase>() { new DiscontinuityPoint(Point1.ToPointD()) };
                }
            }
            CreateComponents(Pad.CreatePoint(pointName, SpareCoordinate_, true, collections));
        }
        public void CreateComponents(PointBase pt1, PointBase pt2)
        {
            if (pt1 == null || pt2 == null) return;
            CreateComponents(pt1);
            CreateComponents(pt2, true);
        }
        public override bool CanDrawVirtual
        {
            get
            {
                return Point1 != null;
            }
        }
        public override void CreateComponents()
        {
            if (Point1 == null)
            {
                CreateComponents($"{Resources.Translate("Point")}1");
            }
            else
            {
                CreateComponents($"{Resources.Translate("Point")}2");
            }
        }
    }
}
